perm filename TCPPRC.MAC[IP,SYS] blob sn#680227 filedate 1982-10-14 generic text, type T, neo UTF8
;CWL:<403-TCP>TCPPRC.MAC.40303 26-Apr-82 17:32:47, Edit by CLYNN
; Remove section 0 restriction on BG and IP; More error returns
;<403-TCP>TCPPRC.MAC.40301 29-Jan-82 15:06:54, Edit by CLYNN
; Updated for TCP release 3
; TCPCKT in STG is check interval
;[BBNF]<401-TCP>TCPPRC.MAC.18, 10-Jul-81 16:12:00, Ed: CLYNN
; Fix: Error returns from initialization routines

	SEARCH	INPAR,TCPPAR,PROLOG
	TTITLE	TCPPRC
	SUBTTL	TCP Process, William W. Plummer, 1Mar79

COMMENT	!

This is the top level of the TCP protocol module.  Herein are the
TCP initialization, "interprocess communication" between parts of
the TCP, etc.


* SIGNAL ...  3 ...... Signal a TCP process to run
  SIGNL0 ...  4 ...... Guts of SIGNAL

* TCPPRC ...  5 ...... Top level of TCP processing
* TCPCHK ...  6 ...... Set next TCP wakeup time
  TCPRUN ...  7 ...... Run any TCP processes that are due
              8 ...... Process table
  DQTASK ...  9 ...... Remove a TCB from process input queue
* TCPTSK ... 10 ...... Run a TCP task on a particular TCB

* TCPINI ... 11 ...... Initialize entire TCP
	!

; SIGNAL		Cause a process to run.

;T1/	(Extended) Target process ID
;T2/	0 or delta in milliseconds
;TCB/	(Extended) Locked Connection Block
;
;	CALL SIGNAL
;Ret+1:	Always

SIGNAL::TEMP <LCK,FN,PRC,DL>
	DMOVEM T1,PRC
	ADD DL,TODCLK		; Compute deadline
	XMOVEI LCK,PRCLCK(PRC)	; Pointer to lock cell of process
	XMOVEI FN,SIGNL0	; Function
	; PRC and DL have args to SIGNL0
	CALL LCKCAL		; Lock the lock and call the function
	RESTORE
	RET

; SIGNL0	Guts of the Signal

;T1/	(Extended) Process block (locked)
;T2/	Wakeup TODCLK
;TCB/	(Extended) Connection block (locked)
;			NOINT
;	CALL SIGNL0
;Ret+1:	Always

SIGNL0:	LOCAL <PRC,DL,SAVTCB>
	DMOVEM T1,PRC		; Save Process and Deadline
	MOVEM TCB,SAVTCB	; Save the signalee
	MOVE T3,TODCLK		; Now in milliseconds
	MOVEM T3,PRCSGT(PRC)	; Set time of most recent signal
	SKIPN @PRCQOF(PRC)	;@TCBQxx(TCB) This TCB already Q'd for task?
	  JRST SIGNL1		; No. Just insert in queue.
	XMOVEI T1,@PRCQOF(PRC)	;@TCBQxx(TCB) Get pointer to queue in the TCB
	CAML DL,@PRCWOF(PRC)	;@TCBTxx(TCB) Compare with deadline already set
	  JRST SIGNL5		; Leave in current position.
	CALL DQ			; Sooner.  Dequeue so it can be inserted
SIGNL1:	MOVEM DL,@PRCWOF(PRC)	;@TCBTxx(TCB) NB double idx, here and elsewhere
	MOVE T2,PRCQ(PRC)	; Pointer to input queue head
	MOVE T3,PRCQOF(PRC)	; Get offset to queue in TCB
SIGNL2:	LOAD T2,QNEXT,(T2)	; Get next TCB on input queue
	SETSEC T2,INTSEC	; Make extended address
	CAMN T2,PRCQ(PRC)	; Back to head?
	  JRST SIGNL4		; Yes.  Append to end of queue.
	MOVE TCB,T2		; Make right for indirect index
	SUBI TCB,0(T3)		; Make TCB point to base of block
	CAML DL,@PRCWOF(PRC)	;@TCBTxx(TCB) Found place to insert?
	  JRST SIGNL2		; No. Scan more of queue

SIGNL4:	MOVE TCB,SAVTCB		; Point TCB at the signalee
	XMOVEI T1,@PRCQOF(PRC)	; Get pointer to queue in that TCB
	CALL NQ			; And queue it up

SIGNL5:	MOVE TCB,PRCQ(PRC)	; Pointer to input queue head
	LOAD TCB,QNEXT,(TCB)	; Get first TCB on the queue
	SUB TCB,PRCQOF(PRC)	; Make into standard TCB pointer
	SETSEC TCB,INTSEC	; Make extended address
	MOVE T1,@PRCWOF(PRC)	;@TCBTxx(TCB) Get wakeup time of 1st TCB on Q
	MOVEM T1,PRCWAK(PRC)	; That is new wakeup for process
	MOVE TCB,SAVTCB		; Restore TCB pointer for caller
	CAMG T1,TODCLK		; Wakeup already gone by?
	  AOS TCPFLG		; Yes. Ensure that we keep running.
	AOS INTFLG		; Cause Internet fork run TCPCHK
	RESTORE
	RET

; TCPPRC		TCP processing

;	(No args)
;
;	CALL TCPPRC		(From Internet fork)
;Ret+1:	Always.

TCPPRC::SETZM TCPFLG		; Clear run request

	SKIPE INTSVR		; Internet level needs space badly?
	  SETZM BG+PRCWAK	; Yes.  Make BG scavenge what it can

	XMOVEI T1,IP		; Select Input Processor
	MOVE T2,TCPIPQ		; (Ext) Ptr to TCP input queue head
	LOAD T3,QNEXT,(T2)	; Get first thing on the queue
	CAIE T3,0(T2)		; Empty if that is the head.
	  CALL TCPTSK		; Process any available input packets

	CALL TCPRUN		; Run all the other "processes"

	XMOVEI T1,BG		; Ptr to Background Process
	MOVE T2,PRCWAK(T1)	; Wakeup time for BG
	CAMG T2,TODCLK		; Due for a run?
	  CALL TCPTSK		; Yes.  Run BG.

	CALL TVTOPR		; Operate TCP Virtual Terminals

	SKIPE TCPFLG		; Further work to do?
	  JRST TCPPRC		; Yes.
	RET

; TCPCHK		Periodic check on TCP

;T1/	A TODCLK to be min'd against
;
;	CALL TCPCHK		; From Internet fork
;Ret+1:	Always.  T1 as min of arg and next TCP check time
;		 TCPTIM set to next run time

TCPCHK::LOCAL <TOD>
	MOVEM T1,TOD
	MOVE T1,TODCLK		; Now.
	ADD T1,TCPCKT		; Check again in 10 seconds
	SKIPN TCPON		; Is the TCP on right now?
	  JRST TCPCH9		; No.

	MOVSI T2,-NPROCS	; Set to scan process table
TCPCH1:	MOVE T3,PRCTAB(T2)	; Get pointer to process block
	SKIPL T4,PRCWAK(T3)	; Avoid ones which aren't scheduled
	 CAML T4,T1		; Less than current best min?
	  CAIA			; No.
	   MOVE T1,T4		; Yes.  Take the new value
	AOBJN T2,TCPCH1		; Loop over all processes in the table

	SKIPL T4,BG+PRCWAK	; Special case background
	 CAML T4,T1
	  CAIA
	   MOVE T1,T4

TCPCH9:	MOVEM T1,TCPTIM		; Save for scheduler test
	CAMLE T1,TOD		; Min against arg
	  MOVE T1,TOD
	RESTORE
	RET

; TCPRUN		Run all the TCP tasks

; Each process has an input queue of TCBs.  TCPRUN scans all "processes"
; and for each with a non-empty queue, calls the approriate routine for
; each TCB on the queue.  The new wake up time is set into the process
; block.

;	CALL TCPRUN
;Ret+1:	Always.

TCPRUN:	LOCAL <I,PRC>
	PUSH P,TCB
	MOVSI I,-NPROCS		; Set to scan all processes
TCPRU1:	MOVE PRC,PRCTAB(I)	; Get pointer to process block
TCPRU2:	SKIPGE T1,PRCWAK(PRC)	; Get the wakeup time for this one
	  JRST TCPRU9		; No run needed

	MOVE T4,PRCQ(PRC)	; Get pointer to queue head
	LOAD T3,QNEXT,(T4)	; Get first thing on the input queue
	SETSEC T3,INTSEC	; Make extended address
	CAMN T3,T4		; Empty queue?
	  JRST TCPRU8		; Yes.  Cancel this process.
	CAMLE T1,TODCLK		; Time to run?
	  JRST TCPRU9		; No.  Try next process

	XMOVEI T1,PRCLCK(PRC)	; The lock to lock
	XMOVEI T2,DQTASK	; The function to call
	MOVE T3,PRC		; Process to work on
	CALL LCKCAL		; Lock the lock and call the function
	MOVE TCB,T1		; Put in standard place

	XMOVEI T1,TCBLCK(TCB)	; The lock on the TCB
	XMOVEI T2,TCPTSK	; Subfunction to call
	MOVE T3,PRC		; The task to run
	CALL LCKCAL		; Lock the TCB and run the function
	JRST TCPRU2		; See if next TCB is due

TCPRU8:	SETO T1,		; Empty queue means no wakeup
	MOVEM T1,PRCWAK(PRC)	; Set into process block
TCPRU9:	AOBJN I,TCPRU1		; Loop over all processes in table
	POP P,TCB
	RESTORE
	RET

; Table of process block pointers:

PRCTAB:	IFIW!RA		; Reassembler
	IFIW!PZ		; Packetizer
	IFIW!RX		; Retransmitter
	IFIW!DG		; Delayed Actions
NPROCS==.-PRCTAB

; Note that BG is special in that it does not have an input queue
; and that it must lock TCBH while it is running.  IP is also special
; because it is driven by packets arriving from the network.

; DQTASK removes a TCB from a task input queue and resets the wakeup
;	 time for that task
;
;T1/	Process block pointer
;			NOINT
;	CALL DQTASK
;Ret+1:	Always.  T1 has pointer to TCB.

DQTASK:	LOCAL <PRC,PROCQ>
	PUSH P,TCB
	MOVEM T1,PRC
	MOVE PROCQ,PRCQ(PRC)	; Pointer to input queue
	LOAD TCB,QNEXT,(PROCQ)	; Get 1st item on the queue
	SETSEC TCB,INTSEC	; Make extended address
	MOVE T1,TCB		; This the one to return
	CALL DQ			; Remove it from the queue
	MOVE T2,PRCQOF(PRC)	; Get offset to queue word in TCB
	SUBI T1,0(T2)		; Get standard TCB pointer

	LOAD TCB,QNEXT,(PROCQ)	; Get 1st item on remaining queue
	SETSEC TCB,INTSEC	; Make extended address
	CAMN TCB,PROCQ		; Is the queue now empty?
	  JRST DQTAS8		; Yes.
	SUBI TCB,0(T2)		; Get pointer to base of TCB
	SKIPA T2,@PRCWOF(PRC)	; Note double index by PRC and TCB
DQTAS8:	  SETO T2,		; No need to run
	MOVEM T2,PRCWAK(PRC)	; Set new wakeup
	POP P,TCB
	RESTORE
	RET

; TCPTSK(Process)	Call the process routine and do accounting

;T1/	(Extended) Process block pointer
;TCB/	(Extended) Locked Connection Block, unless IP or BG being run
;
;	CALL TCPTSK
;Ret+1:	Always

TCPTSK::LOCAL <PRC>
	MOVEM T1,PRC
	MOVEM PRC,PROC		; Indicate who is running now.

	SKIPN STATF		; Taking statistics right now?
	  JRST TCPTS9		; No.  Just call the function
	XMOVEI T1,BG
	XMOVEI T2,IP
	CAME PRC,T1		; Running Background?
	 CAMN PRC,T2		; Running Input Processor?
	  JRST TCPTS8		; Yes.  Activate delay not defined
	MOVEI T1,ACDLAY		; Select activation delay histogram
	MOVE T2,TODCLK		; Now
	SUB T2,PRCSGT(PRC)	; Time of most recent signal
	CALL DOHIST		; Histogram that delta
TCPTS8:
	MOVE T1,PRCTMR(PRC)	; Pointer to appropriate timer
	MOVE T2,PRCROU(PRC)	; The routine to call
	CALL TIMCAL		; Time the call
	JRST TCPTSX

TCPTS9:	CALL @PRCROU(PRC)	; Call the routine
TCPTSX:	AOS TASKCT		; Count tasks run
	AOS @PRCRNC(PRC)	; Count runs of this particular process
	SETZM PROC		; Indicate nobody running now.
	RESTORE
	RET

; TCPINI		Initialize TCP module

;	(no args)
;
;	CALL TCPINI		(From INTINI)
;Ret+1:	Always.  TCP ready to run.

TCPINI::NOSKED

	MOVEI T1,QSZ		; Size of a queue head
	CALL GETBLK		; Get that amount of free storage
	JUMPE T1,TCPINX		; Lose
	MOVEM T1,TCPIPQ		; That is the TCP input queue
	CALL INITQ		; Initialize it

	CALL TBFINI		; Initialize Buffer Windows

	CALL PZINI		; Initialize Packetizer
	JUMPE T1,TCPINX		; Lose

	CALL IPINI		; Initialize Input Processor
	JUMPE T1,TCPINX		; Lose

	CALL RAINI		; Initialize Reassembler
	JUMPE T1,TCPINX		; Lose

	CALL RXINI		; Initialize Retransmitter
	JUMPE T1,TCPINX		; Lose

	CALL DGINI		; Initialize Delayed Action Generator
	JUMPE T1,TCPINX		; Lose

	CALL BGINI		; Initialize Background Routine
	JUMPE T1,TCPINX		; Lose

	CALL USRINI		; Initialize User Interface
	JUMPE T1,TCPINX		; Lose

	CALL STSINI		; Initialize Statistics

	CALL PPINI		; Initialize Packet Printer

	CALL TCBINI		; Initialize TCB Hash table
	JUMPE T1,TCPINX		; Lose

				; All ok
	SETZM TCPSID		; Clear TCP segment idents.
	SETOM TCPIFG		; TCP has now been initialized
	SETOM TCPON		; The TCP is now on

TCPINX:	OKSKED
	RET